<?php

namespace App\Kuafu\Activity\Service;

use App\Kuafu\Activity\Enum\ActivityCodeEnum;
use App\Kuafu\Activity\Enum\ActivityEnum;
use App\Kuafu\Activity\Model\ActivityCouponMappingModel;
use App\Kuafu\Activity\Model\ActivityImageMappingModel;
use App\Kuafu\Activity\Model\ActivityModel;
use App\Kuafu\Activity\Exceptions\ActivityException;
use App\Kuafu\Activity\Model\ActivityProductMappingModel;
use App\Kuafu\Activity\Model\ActivityShopMappingModel;
use App\Kuafu\Activity\Resources\ActivityDetailResource;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Config\Service\ConfigService;
use App\Kuafu\Coupon\Enum\CouponEnum;
use App\Kuafu\Coupon\Model\CouponModel;
use App\Kuafu\CustomerCoupon\Enum\CustomerCouponCodeEnum;
use App\Kuafu\CustomerCoupon\Exceptions\CustomerCouponException;
use App\Kuafu\CustomerCoupon\Model\CustomerCouponModel;
use App\Kuafu\CustomerCoupon\Model\CustomerSendCouponLogModel;
use App\Kuafu\Export\Jobs\QueueExport;
use App\Kuafu\Export\Model\ExportDownloadModel;
use App\Kuafu\Mqtt\Service\MqttService;
use App\Kuafu\Order\Model\OrderCouponSplitModel;
use App\Kuafu\Order\Model\OrderSplitModel;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Shop\Enum\ShopCacheEnum;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\Shop\Model\ShopArchives;
use App\Kuafu\Shop\Model\SourceMaterialTemplateModel;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\Shop\Service\ToolsService;
use App\Kuafu\User\Model\User;
use App\Kuafu\Wechat\Enum\CodeEnum;
use App\Kuafu\Wechat\Exceptions\WechatException;
use App\Kuafu\Wechat\Service\WechatCallbackService;
use App\Kuafu\Wechat\Service\WechatService;
use App\Remote\Tiger\Common\CommonRemote;
use App\Scope\ShopScope;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
use Endroid\QrCode\Writer\PngWriter;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Kuafu\File\FileUtil;

class ActivityService extends BaseService
{
    public static function createActivity(int $brandId, array $data, int $creatorUid)
    {
        // 优惠券绑定
        DB::beginTransaction();
        try {
            $existCouponIds = CouponModel::query()
                                         ->whereIn('id', collect($data['coupons'])->pluck('couponId')->toArray())
                // 如果需要的话，这里加上条件，只用进行中的优惠券
                                         ->pluck('id')
                                         ->toArray();
            if (!count($existCouponIds)) {
                throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_COUPON_EMPTY, '选择的优惠券不能为空');
            }
            $activity               = new ActivityModel;
            $activity->name         = mb_substr($data['name'], 0, 50);
            $activity->status       = ActivityEnum::STATUS_PREPARE;
            $activity->shopType     = $data['shopType'];
            $activity->type         = $data['type'] ?? ActivityEnum::TYPE_REGISTRATION;
            $activity->limitJoinNum = $data["limitJoinNum"] ?? 0;
            if (ActivityEnum::TIME_TYPE_SHORT == $data['timeType']) {
                $activity->startAt = strtotime($data['startAt']);
                $activity->endAt   = strtotime($data['endAt']);
            } else {
                if (ActivityEnum::TIME_TYPE_LONG == $data['timeType']) {
                    // 长期活动
                    $activity->startAt = 0;
                    $activity->endAt   = ActivityEnum::MAX_END_AT;
                    $activity->status  = ActivityEnum::STATUS_RUNNING; // 长期活动直接开始
                }
            }
            $activity->isSmsNotify     = $data['isSmsNotify'] ?? 0;
            $activity->isWechatNotify  = $data['isWechatNotify'] ?? 0;
            $activity->isAttendEd      = $data['isAttendEd'] ?? 0;
            $activity->pushText        = $data['pushText'] ?? '';
            $activity->notifyAheadDays = max(0, $data['notifyAheadDays'] ?? 0);
            $activity->description     = mb_substr($data['description'], 0, 200);
            $activity->brandId         = $brandId;
            $activity->save();
            // 绑定优惠券
            ActivityCouponMappingModel::query()
                                      ->where('activityId', $activity->id)
                                      ->delete();
            ActivityCouponMappingModel::insert(
                collect($data['coupons'])->map(function ($item) use ($existCouponIds, $creatorUid, $activity) {
                    if (!in_array($item['couponId'], $existCouponIds)) {
                        // 过滤掉表里面有问题的优惠券
                        return null;
                    }
                    return [
                        'couponId'     => $item['couponId'],
                        'number'       => $item['num'],
                        'activityId'   => $activity->id,
                        'createdAt'    => time(),
                        'updatedAt'    => time(),
                        'createdByUid' => $creatorUid,
                        'updatedByUid' => $creatorUid,
                    ];
                })->filter()->toArray()
            );

            // 部分选择的店铺
            if ($activity->shopType == ActivityEnum::SHOP_TYPE_SELECTION) {
                $shopIds = Shop::query()
                               ->whereIn('id', $data['shopIds'])
                               ->pluck('id')
                               ->toArray();
                ActivityShopMappingModel::query()
                                        ->where('activityId', $activity->id)
                                        ->delete();
                $insertArr = collect($shopIds)->map(function ($shopId) use ($creatorUid, $activity) {
                    return [
                        'shopId'       => $shopId,
                        'activityId'   => $activity->id,
                        'createdAt'    => time(),
                        'updatedAt'    => time(),
                        'createdByUid' => $creatorUid,
                        'updatedByUid' => $creatorUid,
                    ];
                })->toArray();
                ActivityShopMappingModel::insert($insertArr);
            }
            //如果是注册有礼就添加关联图片
            if (
                in_array($data['type'],
                    [
                        ActivityEnum::TYPE_REGISTRATION,
                        ActivityEnum::TYPE_START_BUSINESS_ACTIVITY
                    ]
                )
            ) {
                $insertImageData = collect($data['imageList'])->map(function ($image) use ($activity) {
                    return [
                        'activityId' => $activity->id,
                        'imageUrl'   => getPicturePath($image),
                        'createdAt'  => time(),
                        'updatedAt'  => time(),
                        'type'       => ActivityImageMappingModel::TYPE_DEFAULT
                    ];
                })->toArray();

                $imagesData = self::getImagesListByTypeParams($data);

                foreach ($imagesData as $datum) {
                    $insertImageData[] = [
                        'activityId' => $activity->id,
                        'imageUrl'   => $datum['imageUrl'],
                        'createdAt'  => time(),
                        'updatedAt'  => time(),
                        'type'       => $datum['type'],
                    ];
                }
                ActivityImageMappingModel::insert($insertImageData);
            }
            DB::commit();

            $linkUrl = vsprintf("pages/activity/store-opening?id=%d&shopId=%d", [
                $activity->id,
                (function () use ($activity) {
                    return $activity->type == ActivityEnum::TYPE_START_BUSINESS_ACTIVITY && $activity->activityShopMappingRel->isNotEmpty() ? $activity->activityShopMappingRel->first()->shopId : 0;
                })()
            ]);

            /*$activity->shortLinkUrl = CommonRemote::generateShortLinkUrl(
                vsprintf("%s%s", [
                    "https://prod-3g8s5v2kb3485d85-1313245501.tcloudbaseapp.com/jump-mp.html?path=",
                    urlencode($linkUrl)
                ])
            )["shortUrl"];*/
            //使用Wx获取小程序 Short Link
            $activity->shortLinkUrl = WechatService::genWxShortLink(
                (function () use ($activity) {
                    return $activity->type == ActivityEnum::TYPE_START_BUSINESS_ACTIVITY && $activity->activityShopMappingRel->isNotEmpty() ? $activity->activityShopMappingRel->first()->shopId : 0;
                })(), $linkUrl, "活动", true);
            $activity->save();

        } catch (Exception $exception) {
            DB::rollBack();
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_DB_ADD);
        }

        // 异步队列任务 来生成活动的二维码+美化
//        dispatch(function () use ($activity) {
        if ($activity->type == ActivityEnum::TYPE_START_BUSINESS_ACTIVITY) {
            $shopId = $activity->activityShopMappingRel->first()->shopId;

            // 给公众号添加图片
            $qrCodeData = ['shopId' => $shopId, 'type' => CodeEnum::APPLET_EVENT_TYPE_ACTIVITY];
            $key        = CodeEnum::APPLET_EVENT_KEY;

            if (isTest()) {
                $qrCode = [
                    "url" => "http://weixin.qq.com/q/02EI4rZiGie-D10000M07p"
                ];
            } else {
                $qrCode = WechatCallbackService::getQrCode($qrCodeData, $key);
            }

            $logoUrl = 'https://file.51kuafu.com/11/52/1472c4bc8afca49491d1375e7a10e1bdcfe9c8f5c973ac51c04f299551d7.png';
            $result  = \Endroid\QrCode\Builder\Builder::create()
                                                      ->writer(new PngWriter())
                                                      ->writerOptions([])
                                                      ->data($qrCode['url'])
                                                      ->encoding(new Encoding('UTF-8'))
                                                      ->errorCorrectionLevel(new ErrorCorrectionLevelHigh())
                                                      ->size(500)
                                                      ->margin(10)
                                                      ->roundBlockSizeMode(new RoundBlockSizeModeMargin())
                                                      ->logoPath($logoUrl)
                                                      ->build();

            $fileName = md5($result->getString()) . '.' . 'png';
            // 设置前缀
            $prefix1         = substr($fileName, 0, 2);
            $prefix2         = substr($fileName, 2, 2);
            $filePath        = '1/00/' . $prefix1 . '/' . $prefix2 . '/';
            $destinationPath = public_path() . '/storage/uploads/images/';
            if (!is_dir($destinationPath . $filePath)) {
                mkdir($destinationPath . $filePath, 0777, true);
            }
            $fullPathFilename = $destinationPath . $filePath . $fileName;
            // 保存文件
            $result->saveToFile($fullPathFilename);

            // 微信上传图片
            if (isTest()) {
                $officialUploadKMediaId = 'QA-Lt4oTEK8yM6Y_qmRAs-3Lax3qdgjHoNUFJYfzc-99IYHlcOSz-5cK-L19HG-VQkh';
            } else {
                $officialFilename       = 'activityId:' . $activity->id . ':' . $fileName;
                $officialUploadKMediaId = WechatCallbackService::uploadOfficialMaterial($fullPathFilename,
                    $officialFilename);
            }

            // 得到了微信的 mediaId, 更新活动图片
            $insertImageData = [
                [
                    'activityId' => $activity->id,
                    'imageUrl'   => $filePath . $fileName,
                    'createdAt'  => time(),
                    'updatedAt'  => time(),
                    'type'       => ActivityImageMappingModel::TYPE_OFFICIAL_IMAGE_GENERATE
                ],
                [
                    'activityId' => $activity->id,
                    'imageUrl'   => $officialUploadKMediaId,
                    'createdAt'  => time(),
                    'updatedAt'  => time(),
                    'type'       => ActivityImageMappingModel::TYPE_OFFICIAL_IMAGE_INNER
                ]
            ];
            // 给小程序添加素材图片
            // 获取小程序封面图的绝对路径
//            $imagesData = self::getImagesListByTypeParams($data);

            if (!empty($data['miniCardImage'])) {
                $path = getPicturePath($data['miniCardImage']);

                $absolutePath = $destinationPath . $path;

                if (isTest()) {
                    $miniCardImageKMediaId = 'QA-Lt4oTEK8yM6Y_qmRAs-3Lax3qdgjHoNUFJYfzc-99IYHlcOSz-5cK-L19HG-VQkh';
                } else {
                    $miniCardImageArr = explode('/', $path);

                    $miniCardOrgFilename     = end($miniCardImageArr);
                    $miniCardCombineFilename = 'activityId:' . $activity->id . ':miniCard:' . $miniCardOrgFilename;
                    $miniCardImageKMediaId   = WechatCallbackService::uploadOfficialMaterial($absolutePath,
                        $miniCardCombineFilename, 'thumb');
                }
                $insertImageData[] = [
                    'activityId' => $activity->id,
                    'imageUrl'   => $miniCardImageKMediaId,
                    'createdAt'  => time(),
                    'updatedAt'  => time(),
                    'type'       => ActivityImageMappingModel::TYPE_MINI_IMAGE_INNER
                ];
            }

            ActivityImageMappingModel::insert($insertImageData);
        }

        // 更新图片 url
//
//        })->onQueue('{QUEUE-GENERATE-IMAGES}');

        // 判断是否符合条件,如果符合直接推送 MQTT

    }

    /**
     * 活动详情，包括统计
     * @param int $id
     * @return array
     * @throws \App\Kuafu\User\Exceptions\UserException
     */
    public static function getActivityById(int $shopId, int $id): array
    {
        $info = static::getActivityInfoById($id);
        /*
        // 发券总量
        $sent = CustomerCouponModel::query()
                                   ->where('activityId', $id)
                                   ->count();
        // 用券总量
        $used = CustomerCouponModel::query()
                                   ->where('activityId', $id)
                                   ->where('status', 1)
                                   ->count();
        // 用券占比
        $percent = $sent ? round((100 * $used / $sent), 2) : 0;
        // 已使用券的用户券id
        $customerCouponIds = CustomerCouponModel::query()
                                                ->where('activityId', $id)
                                                ->pluck('id')
                                                ->toArray();
        // 已使用券的订单id
        $orderIds = OrderCouponSplitModel::suffix($shopId)->query()
                                         ->whereIn('customerCouponId', $customerCouponIds)
                                         ->pluck('orderId')
                                         ->toArray();
        // 订单原价
        $originPrice = OrderSplitModel::suffix($shopId)->query()
                                      ->whereIn('orderId', $orderIds)
                                      ->sum('originalPrice');
        // 订单实付
        $payPrice = OrderSplitModel::suffix($shopId)->query()
                                   ->whereIn('orderId', $orderIds)
                                   ->sum('payPrice');
        // 优惠券本身优惠金额
        $couponDiscountPrice = 0;
        foreach ($info['coupons'] as $coupon) {
            switch ($coupon->type) {
                case CouponEnum::COUPON_TYPE_VOUCHERS:
                    $couponDiscountPrice += $coupon->discount;
                    break;
            }
        }
        // todo 目前只做代金券，没有兑换券和折扣券的信息
        $info['statistics'] = compact('sent', 'used', 'percent', 'originPrice', 'payPrice', 'couponDiscountPrice');
                */
        $info['statistics'] = [];

        // 查询开业活动管理物料模版素材
        list($shopLists, $activityLists) = self::getMaterialDataById([$id]);
        $info['eWechatUrl']  = $shopLists[$shopId]['eWechatUrl'] ?? '';// 企微图片url
        $info['materialUrl'] = $activityLists[$id]['materialUrl'] ?? '';//   生成素材url
        return $info;
    }

    //活动列表
    public static function getActivityList(
        $brandId,
        $name,
        $type,
        $status,
        $createdUserName,
        $shopId,
        $pageSize,
        $pageNum,
        $shopType
    ): array {
        $paginator = ActivityModel::query()
                                  ->where('brandId', $brandId)
                                  ->when(strlen($name), function ($query) use ($name) {
                                      $query->where('name', 'like', "%{$name}%");
                                  })
                                  ->when($type, function ($query) use ($type) {
                                      $query->where('type', $type);
                                  })
                                  ->when(strlen($status), function ($query) use ($status) {
                                      $query->where('status', $status);
                                  })
                                  ->when(strlen($createdUserName), function ($query) use ($createdUserName, $brandId) {
                                      $userIds = User::query()
                                                     ->where('brandId', $brandId)
                                                     ->where('username', 'like', "%{$createdUserName}%")
                                                     ->pluck('id')
                                                     ->toArray();
                                      $query->whereIn('createdByUid', $userIds);
                                  })
                                  ->withGlobalScope("shopScope",
                                      new ShopScope(
                                          function (Builder $builder) {
                                              $shopsType = ShopScope::getShopsType();
                                              $map       = [ActivityEnum::SHOP_TYPE_ALL];
                                              if ($shopsType->unique()->count() == 1) {
                                                  array_push($map, $shopsType->toArray()[0]);
                                              }

                                              $activityId = ActivityShopMappingModel::query()
                                                                                    ->whereIn("shopId",
                                                                                        ShopScope::getShopIdsArr())
                                                                                    ->get()
                                                                                    ->groupBy("activityId")
                                                                                    ->map(function ($v, $k) {
                                                                                        if ($v->count() == count(ShopScope::getShopIdsArr())) {
                                                                                            return $k;
                                                                                        }
                                                                                        return 0;
                                                                                    })->filter()->toArray();

                                              $builder->where(function ($query) use ($map, $activityId) {
                                                  $query
                                                      ->orWhereIn('shopType', $map)
                                                      ->when($activityId, function ($query) use ($activityId) {
                                                          $query->orWhereIn('id', $activityId);
                                                      });
                                              });
                                          }
                                      ))
                                  ->with(['shops', 'coupons', 'createdUser'])
                                  ->orderBy('createdAt', 'desc')
                                  ->paginate($pageSize, ['*'], 'page', $pageNum);

        // 查询开业活动管理物料模版素材
        $activityIds  = collect($paginator->items())
            ->whereIn('type', [
                ActivityEnum::TYPE_START_BUSINESS_ACTIVITY,
                ActivityEnum::TYPE_DAILY_ACTIVITY
            ])
            ->pluck('id')
            ->toArray();
        list($shopLists, $activityLists) = self::getMaterialDataById($activityIds);

        $shopIds = $shopInfos = [];
        collect($paginator->items())
            ->where('type', ActivityEnum::TYPE_START_BUSINESS_ACTIVITY)
            ->map(function ($activity) use (&$shopIds) {
                $shopId = $activity->shopListIds[0] ?? 0;
                if ($shopId) {
                    $shopIds[] = $shopId;
                }
            });
        if ($shopIds) {
            $shopIds   = array_unique($shopIds);
            $shopInfos = Shop::query()
                             ->whereIn('id', $shopIds)
                             ->select(['id', 'shopCode'])
                             ->get()
                             ->keyBy('id')
                             ->toArray();
        }

        return [
            'count'    => $paginator->total(),
            'list'     => $paginator->map(function (ActivityModel $activity) use ($shopLists, $activityLists, $shopInfos) {
                $shopId = $activity->shopListIds[0] ?? 0;
                return [
                    'id'              => $activity->id,
                    'name'            => $activity->name,
                    'activityTime'    => $activity->activityTime,
                    'typeText'        => $activity->typeText,
                    'status'          => $activity->status,
                    'statusText'      => $activity->statusText,
                    'couponNames'     => $activity->coupons->map(function ($coupon) {
                        return $coupon->name;
                    }),
                    'shopNames'       => $activity->shopList,
                    'shopIds'         => $activity->shopListIds,
                    'type'            => $activity->type,
                    'shortLinkUrl'    => $activity->shortLinkUrl,
                    'linkUrl'         => vsprintf("pages/activity/store-opening?id=%d&shopId=%d", [
                        $activity->id,
                        (function () use ($activity) {
                            return in_array($activity->type, [ActivityEnum::TYPE_START_BUSINESS_ACTIVITY, ActivityEnum::TYPE_DAILY_ACTIVITY])
                                &&
                                $activity->activityShopMappingRel->isNotEmpty()
                                    ? $activity->activityShopMappingRel->first()->shopId : 0;
                        })()
                    ]),
                    'createdUserName' => (string)optional($activity->createdUser)->username,
                    'eWechatUrl'      => $shopLists[$shopId]['eWechatUrl'] ?? '',// 企微图片url
                    'materialUrl'     => $activityLists[$activity->id]['materialUrl'] ?? '',// 生成素材url
                    'shopCode'        => $shopInfos[$shopId]['shopCode'] ?? 0,// 门店编号
                ];
            }),
            'pageNum'  => (int)$pageNum,
            'pageSize' => (int)$pageSize,
        ];
    }

    public static function setActivity(int $id, array $data): void
    {
        $query = ActivityModel::query()->find($id);
        if (!$query) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_ID_NOT_EXIST);
        }

        $s = ActivityModel::setData($id, $data);
        if (!$s) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_DB_SET);
        }
    }

    public static function delActivity(int $id): void
    {
        $query = ActivityModel::query()->find($id);
        if (!$query) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_ID_NOT_EXIST);
        }

        $s = ActivityModel::delData($id);
        if (!$s) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_DB_DEL);
        }
    }

    public static function setStatus(int $id, int $status)
    {
        $model = ActivityModel::query()->find($id);
        if (null === $model) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_ID_NOT_EXIST);
        }

        // todo 上架满赠活动校验重叠时间
        if ($model->type == ActivityEnum::TYPE_FULL_GIFT_ACTIVITY && $status == ActivityEnum::STATUS_RUNNING) {
            ActivityModel::query()
                         ->whereIn("status", [ActivityEnum::STATUS_RUNNING, ActivityEnum::STATUS_PREPARE])
                         ->where("type", ActivityEnum::TYPE_FULL_GIFT_ACTIVITY)
                         ->where("id", "<>", $id)
                         ->whereHas("activityShopMappingRel", function ($query) use ($model) {
                             $query->where("shopId", $model->activityShopMappingRel->toArray()[0]["shopId"]);
                         })
                         ->get()
                         ->each(function (ActivityModel $activityModel) use (
                             $model
                         ) {
                             $startCover = $activityModel->startAt >= $model->startAt && $activityModel->startAt <= $model->endAt;
                             $endCover   = $activityModel->endAt >= $model->startAt && $activityModel->endAt <= $model->endAt;
                             $allCover   = $activityModel->startAt < $model->startAt && $activityModel->endAt > $model->endAt;
                             if ($startCover || $endCover || $allCover) {
                                 throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_TIME_COVER);
                             }
                         });
        }

        if ($model->startAt > time() && $model->status != ActivityEnum::STATUS_PREPARE) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_NOT_STARTED, '活动尚未开始');
        }
        if ($model->endAt < time() && $model->status != ActivityEnum::STATUS_PREPARE) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_NOT_STARTED, '活动已结束');
        }
        if (!in_array($status, [ActivityEnum::STATUS_RUNNING, ActivityEnum::STATUS_SUSPEND])) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID, '非法参数');
        }
        $model->status = $status;
        $model->save();
    }

    /**
     * 活动基本信息
     * @param int $activityId
     * @return array
     * @throws ActivityException
     */
    public static function getActivityInfoById(int $activityId): array
    {
        //获取活动基本信息
        $activity = ActivityModel::query()
                                 ->with('shops')
                                 ->find($activityId);
        if (null === $activity) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_ID_NOT_EXIST);
        }

        //获取活动店铺关联
        $shopIds = ActivityShopMappingModel::query()
                                           ->where('activityId', '=', $activityId)
                                           ->select(['shopId'])
                                           ->get();

        //获取活动绑定的优惠券信息以及数量
        $couponList = DB::table('coupons as c')
                        ->leftJoin('activity_coupon_mappings as a', 'c.id', '=', 'a.couponId')
                        ->where(['activityId' => $activityId])
                        ->get();

        $activityImages = $suitProducts = $giftProducts = [];
        switch ($activity->type) {
            case ActivityEnum::TYPE_FULL_GIFT_ACTIVITY:
                $activityProductsRel = $activity->activityProductRel;
                $shopId              = $shopIds[0]["shopId"];
                $shop                = Shop::query()->where("id", $shopId)->first();
                $products            = Product::query()
                                              ->whereIn("id", $activityProductsRel->pluck("productId")->toArray())
                                              ->where("menuId", $shop->menuId)
                                              ->with("categoryRel")
                                              ->get();

                $handledProducts = $activity->activityProductRel->map(function (
                    ActivityProductMappingModel $productMappingModel
                ) use ($products) {
                    $product = $products->where("id", $productMappingModel->productId)->first();
                    return array_merge(
                        collect($productMappingModel->toArray())
                            ->except(["createdAt", "updatedAt", "createdByUid", "updatedByUid"])
                            ->toArray()
                        , [
                            "name"         => attributeGet($product, "name", ""),
                            "imageUrl"     => picturePath(attributeGet($product, "imageUrl", "")),
                            "unit"         => attributeGet($product, "unit", ""),
                            "categoryName" => attributeGet($product, "categoryRel.name", "")
                        ]
                    );
                })->values();

                $suitProducts = $handledProducts->where("type", ActivityProductMappingModel::TYPE_SUIT)->values()->toArray();
                $giftProducts = $handledProducts->where("type", ActivityProductMappingModel::TYPE_GIFT)->values()->toArray();

                break;
            case ActivityEnum::TYPE_REGISTRATION:
            case ActivityEnum::TYPE_START_BUSINESS_ACTIVITY:
            case ActivityEnum::TYPE_DAILY_ACTIVITY:
                $activityImages = ActivityImageMappingService::getImageListById($activityId)->toArray();
                foreach ($activityImages as &$value) {
                    $value = CommonService::joinImageUrl($value['imageUrl']);
                }
                break;
        }

        unset($activity->activityProductRel);
        return [
                'basis'        => $activity->toArray(),
                'shopIds'      => $shopIds->toArray(),
                'coupons'      => $couponList->toArray(),
                'shopList'     => $activity->shopList,
                'imageList'    => $activityImages,
                'suitProducts' => $suitProducts,
                'giftProducts' => $giftProducts,
            ] + self::getImageListByType($activityId);
    }

    public static function getActivityDetailByInfo(int $activityId): array
    {
        //获取活动基本信息
        $activity = ActivityModel::query()
                                 ->with('shops')
                                 ->find($activityId);
        if (null === $activity) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_ID_NOT_EXIST);
        }
        //获取活动店铺关联
        $shopIds = ActivityShopMappingModel::query()
                                           ->where('activityId', '=', $activityId)
                                           ->select(['shopId'])
                                           ->get();

        $lists = ActivityImageMappingModel::getImageListByIdAll($activityId);
        return [
            'basis'     => $activity->toArray(),
            'shopIds'   => $shopIds->toArray(),
            'shopList'  => $activity->shopList,
            'imageList' => $lists,
        ];
    }

    public static function getImageListByType(int $activityId): array
    {
        $list = ActivityImageMappingModel::getImageListByIdNoDefault($activityId);

        $miniCardImage = '';
        $officialImage = '';
        foreach ($list as $item) {
            if ($item['type'] == ActivityImageMappingModel::TYPE_MINI_IMAGE_UPLOAD) {
                $miniCardImage = picturePath($item->imageUrl);
                continue;
            }
            if ($item['type'] == ActivityImageMappingModel::TYPE_OFFICIAL_IMAGE_GENERATE) {
                $officialImage = picturePath($item->imageUrl);
                continue;
            }
        }
        return [
            'miniCardImage' => $miniCardImage,
            'officialImage' => $officialImage,
        ];
    }

    /**
     * 根据活动类型获取正在进行中的活动列表并且满足当前店铺
     * @param $activityType int 活动类型 1 注册有礼
     * @param $shopId int 店铺id
     */
    public static function getActivityIdByShopInfo(int $activityType, int $shopId)
    {
        $status       = ActivityEnum::STATUS_RUNNING;
        $field        = ['id', 'status', 'shopType', 'type', 'createdAt'];
        $activityList = ActivityModel::getActivityListByType($activityType, $status, $field);
        //获取店铺基本信息
        Log::info('绑定手机号发券店铺-店铺id', ['shopId' => $shopId]);
        $shopInfo = ShopService::getShopInfo($shopId);
        if ($shopInfo) {
            $activityList = $activityList->toArray();
            foreach ($activityList as $value) {
                switch ($value['shopType']) {
                    case ActivityEnum::SHOP_TYPE_ALL:
                        //全部
                        return $value['id'];
                    case ActivityEnum::SHOP_TYPE_SELECTION:
                        //部分
                        $shopList = $value['activity_shop_rel'];
                        $shopIds  = array_column($shopList, 'shopId');
                        if (in_array($shopId, $shopIds)) {
                            return $value['id'];
                        }
                        break;
                    default :
                        //加盟/直营
                        if ($shopInfo['type'] == $value['shopType']) {
                            return $value['id'];
                        }
                        break;
                }
            }
        }
        return 0;
    }

    //活动列表
    public static function getAppletActivityList($brandId, $pageSize, $pageNum): array
    {
        $paginator = ActivityModel::query()
                                  ->where('brandId', $brandId)
                                  ->with(['shops', 'coupons', 'createdUser'])
                                  ->orderBy('createdAt', 'desc')
                                  ->paginate($pageSize, ['*'], 'page', $pageNum);

        return [
            'count'    => $paginator->total(),
            'list'     => $paginator->map(function (ActivityModel $activity) {
                return [
                    'id'              => $activity->id,
                    'name'            => $activity->name,
                    'activityTime'    => $activity->activityTime,
                    'typeText'        => $activity->typeText,
                    'status'          => $activity->status,
                    'statusText'      => $activity->statusText,
                    'couponNames'     => $activity->coupons->map(function ($coupon) {
                        return $coupon->name;
                    }),
                    'shopNames'       => $activity->shopList,
                    'createdUserName' => (string)optional($activity->createdUser)->username,
                ];
            }),
            'pageNum'  => (int)$pageNum,
            'pageSize' => (int)$pageSize,
        ];
    }

    /**
     * 根据店铺id反查支持部门分店的活动id
     * @param int $shopId
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public static function getActivityIdsByShopId(int $shopId, int $type, int $brandId)
    {
        return ActivityModel::getActivityIdsByShopId($shopId, $type, $brandId);
    }

    /**
     * 根据活动id列表查询关联店铺信息
     * @param $activityIds
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public static function getShopRelByActivityIds($activityIds)
    {
        return ActivityModel::getShopRelByActivityIds($activityIds);
    }

    /**
     * 根据活动id列表查询关联优惠券信息
     * @param $activityIds
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public static function getCouponRelByActivityIds($activityIds)
    {
        return ActivityModel::getCouponRelByActivityIds($activityIds);
    }

    /**
     * 获取满足全部类型进行中的活动id几个
     * @param $type int 活动类型
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public static function getAllTypeActivityIds(int $type, int $brandId)
    {
        return ActivityModel::getAllTypeActivityIds($type, $brandId);
    }

    /**
     * 根据类型获取正在进行中的活动id和集合
     * @param $shopType
     * @param $type
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public static function getTypeActivityIds($shopType, $type, $brandId)
    {
        return ActivityModel::getTypeActivityIds($shopType, $type, $brandId);
    }

    /**
     * @param int $shopId
     * @param int $uid
     * @param int $activityId
     * @return array
     * @throws ActivityException
     */
    public static function detail(int $shopId, int $uid, int $activityId): array
    {
        try {
            $activity = ActivityModel::query()
                                     ->with([
                                         "activityImageRel" => function ($query) {
                                             $query->where('type', ActivityImageMappingModel::TYPE_DEFAULT);
                                         }
                                     ])
                                     ->where("id", $activityId)
                                     ->first();

            return [
                "activityDetail"            => $activity ? ActivityDetailResource::collection([$activity])
                                                                                 ->getIterator()
                                                                                 ->current() : new \stdClass(),
                "typeActivityJoin"          => ActivityModel::checkJoinShopTypeActivity($shopId, $uid, $activity->type),
                "activityJoin"              => ActivityModel::checkJoinActivity($uid, $activityId),
                "activityCustomerCouponIds" => CustomerCouponModel::query()
                                                                  ->where("userId", $uid)
                                                                  ->where("activityId", $activityId)
                                                                  ->pluck("id")
            ];

        } catch (Exception $exception) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_DETAIL_GET, "获取商品详情失败", $exception);
        }
    }

    /**
     * 更新活动
     *
     * @param object $params
     */
    public static function update(object $params)
    {
        ActivityModel::query()
                     ->where("id", $params->id)
                     ->update(collect((array)$params)->except(["imageList", "timeType", 'miniCardImage'])->toArray());


        ActivityImageMappingModel::query()
                                 ->where("activityId", $params->id)
                                 ->whereIn("type", [
                                     ActivityImageMappingModel::TYPE_DEFAULT,
                                     ActivityImageMappingModel::TYPE_MINI_IMAGE_UPLOAD,
                                     ActivityImageMappingModel::TYPE_MINI_IMAGE_INNER,
                                 ])
                                 ->delete();

        $insertImageData = collect($params->imageList ?? [])->map(function ($image) use ($params) {
            return [
                'activityId' => $params->id,
                'imageUrl'   => getPicturePath($image),
                'createdAt'  => time(),
                'updatedAt'  => time(),
                'type'       => ActivityImageMappingModel::TYPE_DEFAULT
            ];
        })->toArray();


        $imagesData = self::getImagesListByTypeParams(json_decode(json_encode($params), 1));

        foreach ($imagesData as $datum) {
            $insertImageData[] = [
                'activityId' => $params->id,
                'imageUrl'   => $datum['imageUrl'],
                'createdAt'  => time(),
                'updatedAt'  => time(),
                'type'       => $datum['type'],
            ];
        }
        if (!empty($params->miniCardImage)) {
            $path            = getPicturePath($params->miniCardImage);
            $destinationPath = public_path() . '/storage/uploads/images/';

            $absolutePath = $destinationPath . $path;

            if (isTest()) {
                $miniCardImageKMediaId = 'QA-Lt4oTEK8yM6Y_qmRAs-3Lax3qdgjHoNUFJYfzc-99IYHlcOSz-5cK-L19HG-VQkh';
            } else {
                $miniCardImageArr = explode('/', $path);

                $miniCardOrgFilename     = end($miniCardImageArr);
                $miniCardCombineFilename = 'activityId:' . $params->id . ':miniCard:' . $miniCardOrgFilename;
                $miniCardImageKMediaId   = WechatCallbackService::uploadOfficialMaterial($absolutePath,
                    $miniCardCombineFilename, 'thumb');
            }
            $insertImageData[] = [
                'activityId' => $params->id,
                'imageUrl'   => $miniCardImageKMediaId,
                'createdAt'  => time(),
                'updatedAt'  => time(),
                'type'       => ActivityImageMappingModel::TYPE_MINI_IMAGE_INNER
            ];
        }
        ActivityImageMappingModel::query()->insert($insertImageData);
    }

    public static function getImagesListByTypeParams(array $params)
    {
        $imagesList = [];
        if (!empty($params['miniCardImage'])) {
            $imagesList[] = [
                'type'     => ActivityImageMappingModel::TYPE_MINI_IMAGE_UPLOAD,
                'imageUrl' => getPicturePath($params['miniCardImage']),
            ];
        }

        return $imagesList;
    }

    /**
     * 活动管理-私域活动物料素材批量生成
     * @param $activityId
     * @param $rmsUserId
     * @return array
     */
    public static function materialsGeneration($activityId, $rmsUserId): array
    {
        if(self::checkPeakHours()){
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID,
                '用餐高峰时间内禁止导出。请于上午11点之前或下午2点到6点或晚8点之后再使用。');
        }
        $activityModel = ActivityModel::query()->where("id", $activityId)->first();

        $shopId = ActivityShopMappingModel::query()
                                          ->where('activityId', $activityId)
                                          ->value('shopId');
        if (!$shopId) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID, 'shopId不存在');
        }
        $shopDetail = Shop::getShopDetailById($shopId);
        if (!$shopDetail) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID, 'shopInfo不存在');
        }
        $wechatUrl  = ShopArchives::query()->where('shopId', $shopId)->value('eWechatUrl');
        if (!$wechatUrl) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID, '企微图片不存在');
        }

        switch ($activityModel->type){
            case ActivityEnum::TYPE_DAILY_ACTIVITY:
                $fileType = ExportDownloadModel::FILE_TYPE_WEB_GIFT_ACTIVITY_MATERIAL;
                break;
            default:
                $fileType = ExportDownloadModel::FILE_TYPE_WEB_ACTIVITY_MATERIAL;
                break;
        }

        // 查询是否有正在进行中的任务
        $isExport = ExportDownloadModel::query()
                                       ->where('fileType', $fileType)
                                       ->whereIn('status',
                                           [ExportDownloadModel::STATUS_INIT, ExportDownloadModel::STATUS_ING])
                                       ->whereRaw(DB::raw("JSON_CONTAINS(params, JSON_OBJECT('activityId', '{$activityId}'))"))
                                       ->count();
        if ($isExport) {
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_PARAM_VALID, '已存在导出任务，请等待');
        }
        $ids      = ConfigService::getConfigDetail('tools', 'activityMaterialsConfig')['value'];
        $shopName = str_replace(['夸父炸串', '(', ')', '（', '）'], '', $shopDetail->name ?? "");
        $address  = $shopDetail->address ?? '';
        if ($address) {// 详细地址中 省份城市区域，这三个都去掉
            $addressPrefix    = $shopDetail->addressPrefix ?? '';
            $addressPrefixArr = explode('-', $addressPrefix);
            if ($addressPrefixArr) {
                foreach ($addressPrefixArr as $v) {
                    $address = str_replace($v, '', $address);
                }
            }
        }
        $params   = [
            'shopId'      => $shopId,
            'shopCode'    => $shopDetail->shopCode ?? '',
            'showStartAt' => time(),
            'showEndAt'   => time(),
            'activityId'  => $activityId,
            'rmsUserId'   => $rmsUserId,
            'ids'         => $ids,
            'wechatUrl'   => $wechatUrl,
//            'input1'      => "①本券仅限夸父炸串{$shopName}使用;",// 门店名称
//            'input2'      => "②此券每人限领1张,仅限本人凭券到店堂食核销,不可代领;",// 2
//            'input3'      => "③此券不兑换、不找零,不与其他优惠同享.",// 3
//            'input4'      => "地址：{$address}",// 门店地址
            'data'        => [
                'wechatUrl' => $wechatUrl,
                'shopName'  => $shopName,
                'address'   => $address,
//                'input1'    => "①本券仅限夸父炸串{$shopName}使用;",// 门店名称
//                'input2'    => '②此券每人限领1张,仅限本人凭券到店堂食核销,不可代领;',// 2
//                'input3'    => '③此券不兑换、不找零,不与其他优惠同享.',// 3
//                'input4'    => "地址：{$address}",// 门店地址
            ],
        ];

        // 测试打开
        /*foreach ($ids as $id) {$id=137;
            $info = SourceMaterialTemplateModel::query()
                                               ->withoutGlobalScope('isDel')
                                               ->where('id', $id)
                                               ->first();//模版信息
            // 生成文件
            $res = (new ToolsService())->generateTemplateImg($info, $params, $rmsUserId, $shopId);
            dd($res,$id);
        }*/



        $export = (new ExportDownloadModel)->add(
            ExportDownloadModel::CLIENT_TYPE_WEB,
            $fileType,
            $params
        );

        dispatch(new QueueExport($export->id))->onQueue(QueueExport::QUEUE_SOURCE_MATERIAL_TEMPLATE_NAME);
        return [];
    }


    // 查询开业活动管理物料模版素材
    public static function getMaterialDataById($activityIds): array
    {
        $activityLists = [];
        $shopLists     = ActivityShopMappingModel::query()
                                                 ->whereIn('activityId', $activityIds)
                                                 ->select(['shopId', 'activityId'])
                                                 ->get()
                                                 ->keyBy('shopId')
                                                 ->toArray();

        if ($shopLists) {

            // 门店详情中的 企微图片
            ShopArchives::query()
                        ->whereIn('shopId', array_column($shopLists, 'shopId'))
                        ->get()->map(function ($item) use (&$shopLists) {
                    $shopLists[$item->shopId]['eWechatUrl'] = $item->eWechatUrl;
                });

            $activityLists = collect($shopLists)->keyBy('activityId')->toArray();

            // 私域活动物料素材压缩包
            ActivityImageMappingModel::query()
                                     ->whereIn('activityId', $activityIds)
                                     ->where('type', ActivityImageMappingModel::TYPE_MATERIAL_COMPRESS)
                                     ->select(['imageUrl', 'activityId'])
                                     ->get()
                                     ->map(function ($item) use (&$activityLists) {
                                         if (strpos($item->imageUrl, 'export/rms') !== false) {// 源链接
                                             $activityLists[$item->activityId]['materialUrl'] = FileUtil::domain() . '/' . $item->imageUrl;
                                         } else {// 短链
                                             $activityLists[$item->activityId]['materialUrl'] = $item->imageUrl;
                                         }
                                     });
        }
        return [$shopLists, $activityLists];
    }

    /**
     * 用餐高峰时间内禁止导出。请于上午11点之前或下午2点到6点或晚8点之后再使用。
     * @return bool
     */
    public static function checkPeakHours(): bool
    {
        $config = ConfigService::getConfigDetail('tools', 'activityCheckPeakHourConfig',
                getSwitchCacheTime(300))['value'] ?? [];
        if (!$config) {
            return false;
        }
        $now = date('H:i:s'); // 获取当前时间
        $res = false;
        foreach ($config as $temp) {
            if (strtotime($now) >= strtotime($temp['start']) && strtotime($now) <= strtotime($temp['end'])) {
                $res = true;
                break;
            }
        }
        return $res;
    }

    /**
     * 创建活动
     *
     * @param int $uid
     * @param int $type
     * @param object $params
     * @param int $brandId
     * @throws ActivityException
     * @throws WechatException
     * @throws GuzzleException
     */
    public static function createNewActivity(int $uid, int $type, object $params, int $brandId)
    {
        try {
            DB::beginTransaction();
            // todo 主表落库
            $activity = ActivityModel::query()->create(
                collect((array)$params)->except([
                    "imageList",
                    "shopIds",
                    "coupons",
                    "timeType",
                    "giveProducts",
                    "suitProducts"
                ])->merge([
                    "brandId" => $brandId, "type" => $type
                ])->toArray()
            );

            // todo 部分选择的店铺
            if ($activity->shopType == ActivityEnum::SHOP_TYPE_SELECTION) {
                ActivityShopMappingModel::query()->insert(collect($params->shopIds)->map(function ($shopId) use (
                    $uid,
                    $activity
                ) {
                    return [
                        'shopId'       => $shopId,
                        'activityId'   => $activity->id,
                        'createdAt'    => time(),
                        'updatedAt'    => time(),
                        'createdByUid' => $uid,
                        'updatedByUid' => $uid,
                    ];
                })->values()->toArray());
            }

            switch ($type) {
                case ActivityEnum::TYPE_DAILY_ACTIVITY:
                    // todo 关联优惠券落库
                    ActivityCouponMappingModel::query()->insert(
                        collect($params->coupons)->map(function ($item) use ($uid, $activity) {
                            return [
                                'couponId'     => $item['couponId'],
                                'number'       => $item['num'],
                                'activityId'   => $activity->id,
                                'createdAt'    => time(),
                                'updatedAt'    => time(),
                                'createdByUid' => $uid,
                                'updatedByUid' => $uid,
                            ];
                        })->values()->toArray()
                    );

                    // todo 日常活动添加关联图片
                    if ($type == ActivityEnum::TYPE_DAILY_ACTIVITY) {
                        $insertImageData = collect($params->imageList)->map(function ($image) use ($activity) {
                            return [
                                'activityId' => $activity->id,
                                'imageUrl'   => getPicturePath($image),
                                'createdAt'  => time(),
                                'updatedAt'  => time(),
                                'type'       => ActivityImageMappingModel::TYPE_DEFAULT
                            ];
                        })->when(
                            attributeGet($params, "miniCardImage", ""),
                            function ($query) use ($activity, $params) {
                                return $query->merge([
                                    [
                                        'activityId' => $activity->id,
                                        'imageUrl'   => getPicturePath($params->miniCardImage),
                                        'createdAt'  => time(),
                                        'updatedAt'  => time(),
                                        'type'       => ActivityImageMappingModel::TYPE_MINI_IMAGE_UPLOAD
                                    ]
                                ]);
                        })->toArray();

                        ActivityImageMappingModel::query()->insert($insertImageData);
                    }
                    break;
                case ActivityEnum::TYPE_FULL_GIFT_ACTIVITY:
                    // ToDo 关联适用菜品写入
                    if($params->productType == ActivityEnum::PRODUCT_TYPE_PART){
                        ActivityProductMappingModel::query()->insert(
                            collect($params->suitProducts)->map(function ($row) use ($uid, $activity) {
                                return array_merge($row, [
                                    "type"         => ActivityProductMappingModel::TYPE_SUIT,
                                    "activityId"   => $activity->id,
                                    "createdAt"    => time(),
                                    "updatedAt"    => time(),
                                    "createdByUid" => $uid
                                ]);
                            })->values()->toArray()
                        );
                    }


                    // ToDo 关联满赠菜品写入
                    ActivityProductMappingModel::query()->insert(
                        collect($params->giveProducts)->map(function ($row) use ($uid, $activity) {
                            return array_merge($row, [
                                "type"         => ActivityProductMappingModel::TYPE_GIFT,
                                "activityId"   => $activity->id,
                                "createdAt"    => time(),
                                "updatedAt"    => time(),
                                "createdByUid" => $uid
                            ], isset($row["stockNum"]) ? [] : ["stockNum" => 0]);
                        })->values()->toArray()
                    );
                    break;
            }

            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();
            throw new ActivityException(ActivityCodeEnum::ERR_ACTIVITY_DB_ADD);
        }

        self::activityCreatePostOperation($activity->id);
    }

    /**
     * todo 活动创建成功后置操作
     *
     * @param int $activityId
     * @throws WechatException
     * @throws GuzzleException
     */
    public static function activityCreatePostOperation(int $activityId)
    {
        $activity = ActivityModel::query()->where("id", $activityId)->first();

        switch ($activity->type) {
            case ActivityEnum::TYPE_DAILY_ACTIVITY:

                if ($activity->shopType == ActivityEnum::SHOP_TYPE_SELECTION) {
                    $shopId = $activity->activityShopMappingRel->first()->shopId;
                } else {
                    $shopId = 0;
                }

                $cloneActivity = clone $activity;
                // todo 使用Wx获取小程序 Short Link
                $cloneActivity->shortLinkUrl = WechatService::genWxShortLink(
                    $shopId,
                    vsprintf("pages/activity/store-opening?id=%d&shopId=%d", [
                        $activity->id,
                        $shopId
                    ]),
                    "活动",
                    true
                );
                $cloneActivity->save();

                if ($activity->type == ActivityEnum::TYPE_DAILY_ACTIVITY) {
                    // 给公众号添加图片
                    $qrCodeData = ['shopId' => $shopId, 'type' => CodeEnum::APPLET_EVENT_TYPE_ACTIVITY];
                    $key        = CodeEnum::APPLET_EVENT_KEY;

                    if (isTest()) {
                        $qrCode = [
                            "url" => "http://weixin.qq.com/q/02EI4rZiGie-D10000M07p"
                        ];
                    } else {
                        $qrCode = WechatCallbackService::getQrCode($qrCodeData, $key);
                    }

                    $logoUrl = 'https://file.51kuafu.com/11/52/1472c4bc8afca49491d1375e7a10e1bdcfe9c8f5c973ac51c04f299551d7.png';
                    $result  = \Endroid\QrCode\Builder\Builder::create()
                                                              ->writer(new PngWriter())
                                                              ->writerOptions([])
                                                              ->data($qrCode['url'])
                                                              ->encoding(new Encoding('UTF-8'))
                                                              ->errorCorrectionLevel(new ErrorCorrectionLevelHigh())
                                                              ->size(500)
                                                              ->margin(10)
                                                              ->roundBlockSizeMode(new RoundBlockSizeModeMargin())
                                                              ->logoPath($logoUrl)
                                                              ->build();

                    $fileName = md5($result->getString()) . '.' . 'png';
                    // 设置前缀
                    $prefix1         = substr($fileName, 0, 2);
                    $prefix2         = substr($fileName, 2, 2);
                    $filePath        = '1/00/' . $prefix1 . '/' . $prefix2 . '/';
                    $destinationPath = public_path() . '/storage/uploads/images/';
                    if (!is_dir($destinationPath . $filePath)) {
                        mkdir($destinationPath . $filePath, 0777, true);
                    }
                    $fullPathFilename = $destinationPath . $filePath . $fileName;
                    // 保存文件
                    $result->saveToFile($fullPathFilename);

                    // 微信上传图片
                    if (isTest()) {
                        $officialUploadKMediaId = 'QA-Lt4oTEK8yM6Y_qmRAs-3Lax3qdgjHoNUFJYfzc-99IYHlcOSz-5cK-L19HG-VQkh';
                    } else {
                        $officialFilename       = 'activityId:' . $activity->id . ':' . $fileName;
                        $officialUploadKMediaId = WechatCallbackService::uploadOfficialMaterial($fullPathFilename,
                            $officialFilename);
                    }

                    // 得到了微信的 mediaId, 更新活动图片
                    $insertImageData = [
                        [
                            'activityId' => $activity->id,
                            'imageUrl'   => $filePath . $fileName,
                            'createdAt'  => time(),
                            'updatedAt'  => time(),
                            'type'       => ActivityImageMappingModel::TYPE_OFFICIAL_IMAGE_GENERATE
                        ],
                        [
                            'activityId' => $activity->id,
                            'imageUrl'   => $officialUploadKMediaId,
                            'createdAt'  => time(),
                            'updatedAt'  => time(),
                            'type'       => ActivityImageMappingModel::TYPE_OFFICIAL_IMAGE_INNER
                        ]
                    ];
                    // 给小程序添加素材图片
                    // 获取小程序封面图的绝对路径
                    $minCardImg = $activity->activityImageRel->where("type", ActivityImageMappingModel::TYPE_MINI_IMAGE_UPLOAD)->first();
                    if ($minCardImg) {
                        $path         = $minCardImg->imageUrl;
                        $absolutePath = $destinationPath . $path;

                        if (isTest()) {
                            $miniCardImageKMediaId = 'QA-Lt4oTEK8yM6Y_qmRAs-3Lax3qdgjHoNUFJYfzc-99IYHlcOSz-5cK-L19HG-VQkh';
                        } else {
                            $miniCardImageArr = explode('/', $path);

                            $miniCardOrgFilename     = end($miniCardImageArr);
                            $miniCardCombineFilename = 'activityId:' . $activity->id . ':miniCard:' . $miniCardOrgFilename;
                            $miniCardImageKMediaId   = WechatCallbackService::uploadOfficialMaterial($absolutePath,
                                $miniCardCombineFilename, 'thumb');
                        }
                        $insertImageData[] = [
                            'activityId' => $activity->id,
                            'imageUrl'   => $miniCardImageKMediaId,
                            'createdAt'  => time(),
                            'updatedAt'  => time(),
                            'type'       => ActivityImageMappingModel::TYPE_MINI_IMAGE_INNER
                        ];
                    }

                    ActivityImageMappingModel::insert($insertImageData);
                }
                break;
        }

    }

    /**
     * 获取赠品活动信息
     *
     * @param Shop $shop 门店查询模型类
     * @param int $channel 渠道
     * @return array|null
     */
    public static function getShopGiftActivityDetail(Shop $shop, int $channel): ?array
    {
        $activityModel = ActivityModel::query()
                                      ->with(["activityProductRel"])
                                      ->where("type", ActivityEnum::TYPE_FULL_GIFT_ACTIVITY)
                                      ->whereRaw('FIND_IN_SET(?, channel)', [$channel])
                                      ->where("status", ActivityEnum::STATUS_RUNNING)
                                      ->whereHas("activityShopMappingRel", function ($query) use ($shop) {
                                          $query->where("shopId", $shop->id);
                                      })
                                      ->where("startAt", "<", time())
                                      ->where("endAt", ">", time())
                                      ->first();

        if (!$activityModel) {
            return null;
        }

        $productIds = $activityModel->activityProductRel->pluck("productId")->toArray();
        $shopProduct = Product::query()->where("menuId", $shop->menuId)->whereIn("id", $productIds)->get();

        return [
            "id"              => $activityModel->id,
            "name"            => $activityModel->name,
            "type"            => $activityModel->type,
            "startAt"         => $activityModel->startAt,
            "endAt"           => $activityModel->endAt,
            "productType"     => $activityModel->productType,
            "formatStartAt"   => Carbon::createFromTimestamp($activityModel->startAt)->format("Y-m-d H:i:s"),
            "formatEndAt"     => Carbon::createFromTimestamp($activityModel->endAt)->format("Y-m-d H:i:s"),
            "description"     => $activityModel->description,
            "channel"         => $activityModel->channel,
            "thresholdAmount" => $activityModel->thresholdAmount,
            "posAutoJoin"     => $activityModel->posAutoJoin,
            "suitProductIds"  => $activityModel->activityProductRel->where(
                "type", ActivityProductMappingModel::TYPE_SUIT
            )->pluck("productId")->toArray(),
            "giftProductIds"  => $activityModel->activityProductRel->where(
                "type", ActivityProductMappingModel::TYPE_GIFT
            )->map(function (ActivityProductMappingModel $productMappingModel)use($shopProduct) {
                $productName = attributeGet($shopProduct->where("id", $productMappingModel->productId)->first(), "name", "");
                return array_merge($productMappingModel->only(["id", "productId", "giveStockRuleType", "giveNum", "stockNum"]), [
                    "productName" => $productName
                ]);
            })->values()->toArray(),
            "limitJoinNum"    => $activityModel->limitJoinNum
        ];
    }

    /**
     * 查询是否参加过指定的满赠活动
     *
     * @param int $shopId
     * @param int $userId
     * @param int $activity
     * @param array $giftActivity
     * @return bool
     */
    public static function isJoinShopGiftActivity(int $shopId, int $userId, int $activity, array $giftActivity): bool
    {
        //todo 查询参加记录
        $existsJoinCount = CustomerSendCouponLogModel::query()->where("userId", $userId)
                                                       ->where("shopId", $shopId)
                                                       ->where("activityId", $activity)
                                                       ->count();

        if($existsJoinCount >= $giftActivity["limitJoinNum"]){
            return true;
        }

        // ToDo 查询近15分钟待支付订单
        $existsOrderCount = OrderSplitModel::suffix($shopId)->where("userId", $userId)
            ->where("createdAt", ">=", Carbon::now()->subMinutes(15)->timestamp)
            ->where("orderStatus", \App\Kuafu\Order\Enum\CodeEnum::ORDER_STATUS_WAIT_PAY)
            ->whereHas("orderDetailRel", function($query)use($giftActivity){
                $query->whereIn("productId", collect($giftActivity["giftProductIds"])->pluck("productId")->toArray());
            })
            ->count();

        if($existsOrderCount + $existsJoinCount >= $giftActivity["limitJoinNum"]){
            return true;
        }

        return false;
    }
}
